#include "RenderWindow.h"
#include <GL/GL.h>
#include <GL/GLU.h>
#include <Windows.h>
#include "BaseException.h"

namespace Caelum {

void RenderWindow::Initialize(WindowParams &wp, bool IsOnlyRenderWindow)
{
	Window::Initialize(wp);
	mOnlyRW = IsOnlyRenderWindow;

	WinDC = (unsigned long)GetDC((HWND)mWindowPtr);
	if (WinDC == NULL)
		throw new BaseException(L"Couldn't get window device context!");

	PIXELFORMATDESCRIPTOR pfd;
	ZeroMemory(&pfd, sizeof(pfd));

	pfd.cAlphaBits = 8;
	pfd.cColorBits = 32;
	pfd.cDepthBits = 24;
	pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
	pfd.iLayerType = PFD_MAIN_PLANE;
	pfd.iPixelType = PFD_TYPE_RGBA;
	pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
	pfd.nVersion = 1;

	int n = ChoosePixelFormat((HDC)WinDC, &pfd);

	if (!SetPixelFormat((HDC)WinDC, n, &pfd))
		throw new BaseException(L"Couldn't set window pixel format!");

	WinRC = (unsigned long)wglCreateContext((HDC)WinDC);
	wglMakeCurrent((HDC)WinDC, (HGLRC)WinRC);

	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
	glClearDepth(1.0f);
	glEnable(GL_TEXTURE_2D);

	GetClientSize(mWidth, mHeight);
	SetFieldOfView(75);
}

void RenderWindow::GetMetrics(uint &Width, uint &Height, uint &ColorDepth)
{
	Width = mWidth;
	Height = mHeight;
	ColorDepth = mColorDepth;
}

uint RenderWindow::GetWidth() 
{
	return mWidth;
}

uint RenderWindow::GetHeight()
{
	return mHeight;
}

uint RenderWindow::GetColorDepth()
{
	return mColorDepth;
}

void RenderWindow::SetRenderMode(RenderMode Mode)
{
	switch (Mode)
	{
	case RENDERMODE_3D:
		{
			glMatrixMode(GL_PROJECTION);
			glLoadIdentity();
			gluPerspective(mFOV, (float)mWidth / (float)mHeight, 0.1f, 100.0f);
			break;
		}
	case RENDERMODE_2D:
		{
			glMatrixMode(GL_PROJECTION);
			glLoadIdentity();
			gluOrtho2D(0, mWidth, 0, mHeight);
			break;
		}
	default:
		break;
	}
	glMatrixMode(GL_MODELVIEW);
}

void RenderWindow::Update(bool SwapBuffers)
{
	//only call this if we need to, it has some overhead.
	//most applications won't need this, but things like
	//model viewers or editors will find this very useful.
	if (!mOnlyRW)
		wglMakeCurrent((HDC)WinDC, (HGLRC)WinRC);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	if (SwapBuffers)
		this->SwapBuffers();
}

void RenderWindow::SwapBuffers(bool WaitForVSync)
{
	::SwapBuffers((HDC)WinDC);
}

void RenderWindow::Resizing(int NewW, int NewH)
{
	int cw = NewW, ch = NewH;
	mWidth = cw; mHeight = ch;
	glViewport(0, 0, cw, ch);
	SetRenderMode(RENDERMODE_3D);
}

}